
// Linux API
#include <sys/time.h>

// C API
#include <time.h>

#include "Timestamp.hpp"

namespace tulun
{
    // Timestamp::
    // uint64_t micr_; // 微秒
    static uint32_t slen = 128;
    Timestamp::Timestamp() : micr_(0) {}
    Timestamp::Timestamp(uint64_t ms) : micr_(ms) {}
    Timestamp::~Timestamp() {}
    void Timestamp::swap(Timestamp &other)
    {
        std::swap(other.micr_, this->micr_);
    }
    std::string Timestamp::toString() const
    {
        char buff[slen] = {};
        time_t sec = micr_ / kMicPerSec;
        time_t mic = micr_ % kMicPerSec;
        sprintf(buff, "%lu.%luZ", sec, mic);
        return std::string(buff);
    }
    // "1234567.3456Z";
    std::string Timestamp::toFormattedString(bool showmicro) const
    {
        char buff[slen] = {};
        time_t sec = micr_ / kMicPerSec;
        time_t mic = micr_ % kMicPerSec;
        struct tm tm_time;
        localtime_r(&sec, &tm_time);
        int pos = sprintf(buff, "%04d/%02d/%02d %02d:%02d:%02d",
                          tm_time.tm_year + 1900,
                          tm_time.tm_mon + 1,
                          tm_time.tm_mday,
                          tm_time.tm_hour,
                          tm_time.tm_min,
                          tm_time.tm_sec);
        if (showmicro)
        {
            sprintf(buff + pos, ".%ldZ", mic);
        }
        return std::string(buff);
    }
    // "2025/6/10 10:56:12"
    // "2025/6/10 10:56:12.4567Z"
    std::string Timestamp::toFormattedFile() const
    {
        char buff[slen] = {};
        time_t sec = micr_ / kMicPerSec;
        time_t mic = micr_ % kMicPerSec;
        struct tm tm_time;
        localtime_r(&sec, &tm_time);
        int pos = sprintf(buff, "%04d%02d%02d%02d%02d%02d",
                          tm_time.tm_year + 1900,
                          tm_time.tm_mon + 1,
                          tm_time.tm_mday,
                          tm_time.tm_hour,
                          tm_time.tm_min,
                          tm_time.tm_sec);
        sprintf(buff + pos, ".%ldZ", mic);
        return std::string(buff);
    }
    // 20250610105612.4567
    bool Timestamp::valid() const
    {
        return micr_ > 0;
    }
    uint64_t Timestamp::getmicro() const
    {
        return micr_;
    }
    uint64_t Timestamp::getsecond() const
    {
        return micr_ / kMicPerSec;
    }
    const Timestamp &Timestamp::now()
    {
        *this = Timestamp::Now();
        return *this;
    }
    Timestamp::operator uint64_t() const
    {
        return micr_;
    }

    // static
    Timestamp Timestamp::Now()
    { // time; 1970 1 1 0:0:0 ---> 2025 6 10 12:06:34
        struct timeval tv;
        ::gettimeofday(&tv, nullptr);
        return Timestamp(tv.tv_sec * kMicPerSec + tv.tv_usec);
    }
    Timestamp Timestamp::Invalid()
    {
        return Timestamp(0);
    }

} // namespace tulun
